<template>
  <div class="dropdown-menu" ref="dropdownRef" @click.stop="handleClick">
    <slot></slot>
  </div>

  <teleport to="body" v-if="showMenu">
    <div class="dropdown-menu-content" ref="menuRef" v-clickOutside="() => (showMenu = false)">
      <div
        class="item"
        v-for="(item, index) in options"
        :key="index"
        @click.stop="(e) => itemClick(item, e)"
      >
        <Icon v-if="item.icon" :prefix="item.iconPrefix || ''" :name="item.icon" />
        <div
          v-if="item.url"
          class="img"
          :style="{
            'background-image': `url(${item.url})`,
          }"
        ></div>
        <span>{{ item.label }}</span>
      </div>
    </div>
  </teleport>
</template>

<script setup lang="ts">
  import { nextTick, ref, watch } from 'vue';

  import type { DropdownMenuOptions } from '#/components';

  defineOptions({
    name: 'CsDropdownMenu',
  });

  const emit = defineEmits(['click', 'dropMenuOpen']);
  const props = defineProps<{
    options: DropdownMenuOptions;
  }>();

  const menuRef = ref();
  const dropdownRef = ref();
  const showMenu = ref(false);

  watch(showMenu, (val) => {
    emit('dropMenuOpen', val);
  });

  function handleClick() {
    const { options } = props;
    if (!options || options.length > 0) {
      showMenu.value = true;
      nextTick(() => {
        handlePosition();
      });
    }
  }

  function itemClick(data, e) {
    showMenu.value = false;
    emit('click', data.value, e);
  }

  function handlePosition() {
    let left = '';
    let top = '';
    const rect = dropdownRef.value.getBoundingClientRect();
    const clientX = rect.left;
    const clientY = rect.bottom;
    // 当前浏览器视口宽高
    const { innerWidth, innerHeight } = window;
    // 获取自定义菜单的宽度
    const { offsetWidth, offsetHeight } = menuRef.value;
    // right 点击处右侧能放下，反则放不下
    const right = innerWidth - clientX > offsetWidth;
    // bottom 点击处下面能放下，反则放不下
    const bottom = innerHeight - clientY > offsetHeight;

    if (right) {
      left = `${clientX}px`;
    } else {
      left = `${clientX - offsetWidth}px`;
    }
    if (bottom) {
      top = `${clientY}px`;
    } else {
      top = `${clientY - offsetHeight}px`;
    }

    menuRef.value.style.top = top;
    menuRef.value.style.left = left;
  }
</script>

<style scoped lang="less">
  .dropdown-menu-content {
    position: fixed;
    z-index: 2500;
    min-width: 128px;
    max-height: 240px;
    overflow-y: auto;
    border: 1px solid transparent;
    background: linear-gradient(180deg, rgb(6 41 74 / 64%) 0%, rgb(6 41 74 / 26%) 100%);
    backdrop-filter: blur(8px);
    border-image: linear-gradient(180deg, rgb(26 255 251 / 20%) 0%, rgb(26 255 251 / 100%) 100%);
    border-image-slice: 1;

    .item {
      display: flex;
      align-items: center;
      height: 32px;
      padding: 0 8px;
      cursor: pointer;

      &:hover {
        background: linear-gradient(90deg, rgb(41 233 194 / 80%) 0%, rgb(55 219 157 / 28%) 100%);

        span {
          color: rgb(255 255 255 / 100%);
        }

        .td-icon {
          fill: rgb(255 255 255 / 100%);
        }
      }

      .td-icon {
        width: 16px;
        height: 16px;
        margin-right: 6px;
        fill: rgb(153 206 251 / 100%);
      }

      .img {
        width: 16px;
        height: 16px;
        margin: 0 5px 0 11px;
        background-repeat: no-repeat;
        background-position: center;
        background-size: contain;
      }

      span {
        color: rgb(153 206 251 / 100%);
        font-size: 14px;
        font-weight: 400;
      }
    }
  }
</style>
